package com.openroom.ui;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.Transparency;

import org.apache.pivot.wtk.Component;
import org.apache.pivot.wtk.Dimensions;
import org.apache.pivot.wtk.HorizontalAlignment;
import org.apache.pivot.wtk.ImageView;
import org.apache.pivot.wtk.Mouse.Button;
import org.apache.pivot.wtk.VerticalAlignment;
import org.apache.pivot.wtk.media.Image;
import org.apache.pivot.wtk.skin.ImageViewSkin;

/**
 * Custom ImageViewSkin which is focusable.
 */
public class FocusableImageViewSkin extends ImageViewSkin {
	private Color backgroundColor = null;
	private float opacity = 1.0f;
	private HorizontalAlignment horizontalAlignment = HorizontalAlignment.CENTER;
	private VerticalAlignment verticalAlignment = VerticalAlignment.CENTER;

	private boolean fill = false;
	private boolean preserveAspectRatio = true;

	private int imageX = 0;
	private int imageY = 0;
	private float scaleX = 1;
	private float scaleY = 1;

	private static final int OFFSET = 4;

	@Override
	public int getPreferredWidth(int height) {
		ImageView imageView = (ImageView) getComponent();
		Image image = imageView.getImage();

		return (image == null) ? 0 : image.getWidth() + OFFSET;
	}

	@Override
	public int getPreferredHeight(int width) {
		ImageView imageView = (ImageView) getComponent();
		Image image = imageView.getImage();

		return (image == null) ? 0 : image.getHeight() + OFFSET;
	}

	@Override
	public Dimensions getPreferredSize() {
		ImageView imageView = (ImageView) getComponent();
		Image image = imageView.getImage();

		return (image == null) ? new Dimensions(0, 0) : new Dimensions(
				image.getWidth() + OFFSET, image.getHeight() + OFFSET);
	}

	@Override
	public int getBaseline(int width, int height) {
		ImageView imageView = (ImageView) getComponent();
		Image image = imageView.getImage();

		int baseline = -1;

		if (image != null) {
			baseline = image.getBaseline();

			if (baseline != -1) {
				Dimensions imageSize = image.getSize();

				if (fill) {
					// Scale to fit
					if (preserveAspectRatio) {
						float aspectRatio = (float) width / (float) height;
						float imageAspectRatio = (float) imageSize.width
								/ (float) imageSize.height;

						if (aspectRatio > imageAspectRatio) {
							baseline *= (float) height
									/ (float) imageSize.height;
						} else {
							float scaleY = (float) width
									/ (float) imageSize.width;
							baseline *= scaleY;
							baseline += (int) (height - imageSize.height
									* scaleY) / 2;
						}
					} else {
						baseline *= (float) height / (float) imageSize.height;
					}
				} else {
					if (verticalAlignment == VerticalAlignment.CENTER) {
						baseline += (height - imageSize.height) / 2;
					} else if (verticalAlignment == VerticalAlignment.BOTTOM) {
						baseline += height - imageSize.height;
					}
				}
			}
		}

		return baseline;
	}

	@Override
	public void layout() {
		ImageView imageView = (ImageView) getComponent();
		Image image = imageView.getImage();

		if (image != null) {
			int width = getWidth();
			int height = getHeight();

			Dimensions imageSize = image.getSize();

			if (fill) {
				// Scale to fit
				if (preserveAspectRatio) {
					float aspectRatio = (float) width / (float) height;
					float imageAspectRatio = (float) imageSize.width
							/ (float) imageSize.height;

					if (aspectRatio > imageAspectRatio) {
						imageY = 0;
						scaleY = (float) height / (float) imageSize.height;

						imageX = (int) (width - imageSize.width * scaleY) / 2;
						scaleX = scaleY;
					} else {
						imageX = 0;
						scaleX = (float) width / (float) imageSize.width;

						imageY = (int) (height - imageSize.height * scaleX) / 2;
						scaleY = scaleX;
					}
				} else {
					imageX = 0;
					scaleX = (float) width / (float) imageSize.width;

					imageY = 0;
					scaleY = (float) height / (float) imageSize.height;
				}
			} else {
				if (horizontalAlignment == HorizontalAlignment.CENTER) {
					imageX = (width - imageSize.width) / 2;
				} else if (horizontalAlignment == HorizontalAlignment.RIGHT) {
					imageX = width - imageSize.width;
				} else {
					imageX = 0;
				}

				scaleX = 1.0f;

				if (verticalAlignment == VerticalAlignment.CENTER) {
					imageY = (height - imageSize.height) / 2;
				} else if (verticalAlignment == VerticalAlignment.BOTTOM) {
					imageY = height - imageSize.height;
				} else {
					imageY = 0;
				}

				scaleY = 1.0f;
			}
		}
	}

	@Override
	public void paint(Graphics2D graphics) {

		ImageView imageView = (ImageView) getComponent();
		Image image = imageView.getImage();

		int width = getWidth();
		int height = getHeight();

		if (backgroundColor != null) {
			graphics.setPaint(backgroundColor);
			graphics.fillRect(0, 0, width + 15, height + 15);
		}

		if (image != null) {
			Graphics2D imageGraphics = (Graphics2D) graphics.create();
			imageGraphics.translate(2, 2);
			imageGraphics.scale(scaleX, scaleY);

			// Apply an alpha composite if the opacity value is less than
			// the current alpha
			float alpha = 1.0f;

			Composite composite = imageGraphics.getComposite();
			if (composite instanceof AlphaComposite) {
				AlphaComposite alphaComposite = (AlphaComposite) composite;
				alpha = alphaComposite.getAlpha();
			}

			if (opacity < alpha) {
				imageGraphics.setComposite(AlphaComposite.getInstance(
						AlphaComposite.SRC_OVER, opacity));
			}

			image.paint(imageGraphics);
			imageGraphics.dispose();
		}
	}

	/**
	 * @return <tt>false</tt>; image views are not focusable.
	 */
	@Override
	public boolean isFocusable() {
		return false;
	}

	@Override
	public boolean isOpaque() {
		return (backgroundColor != null && backgroundColor.getTransparency() == Transparency.OPAQUE);
	}

	public Color getBackgroundColor() {
		return backgroundColor;
	}

	public void setBackgroundColor(Color backgroundColor) {
		this.backgroundColor = backgroundColor;
		repaintComponent();
	}

	public float getOpacity() {
		return opacity;
	}

	public void setOpacity(float opacity) {
		if (opacity < 0 || opacity > 1) {
			throw new IllegalArgumentException("Opacity out of range [0,1].");
		}

		this.opacity = opacity;
		repaintComponent();
	}

	public HorizontalAlignment getHorizontalAlignment() {
		return horizontalAlignment;
	}

	public void setHorizontalAlignment(HorizontalAlignment horizontalAlignment) {
		if (horizontalAlignment == null) {
			throw new IllegalArgumentException("horizontalAlignment is null.");
		}

		this.horizontalAlignment = horizontalAlignment;
		layout();
		repaintComponent();
	}

	public VerticalAlignment getVerticalAlignment() {
		return verticalAlignment;
	}

	public void setVerticalAlignment(VerticalAlignment verticalAlignment) {
		if (verticalAlignment == null) {
			throw new IllegalArgumentException("verticalAlignment is null.");
		}

		this.verticalAlignment = verticalAlignment;
		layout();
		repaintComponent();
	}

	public boolean getFill() {
		return fill;
	}

	public void setFill(boolean fill) {
		this.fill = fill;
		layout();
		repaintComponent();
	}

	public boolean getPreserveAspectRatio() {
		return preserveAspectRatio;
	}

	public void setPreserveAspectRatio(boolean preserveAspectRatio) {
		this.preserveAspectRatio = preserveAspectRatio;
		layout();
		repaintComponent();
	}

	@Override
	public void asynchronousChanged(ImageView imageView) {
		// No-op
	}

	public FocusableImageViewSkin() {
		super();
	}

	@Override
	public boolean mouseDown(Component component, Button button, int x, int y) {
		if (button == Button.LEFT) {
			// Assign focus to the ImageView when it receives a left click
			component.requestFocus();
			Boolean object = (Boolean) getComponent().getUserData().get(
					"SELECTED");
			if (object != null) {

			}
		}
		return super.mouseDown(component, button, x, y);
	}

}